﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    
    internal class CFExRecord : WorksheetLevelRecord, IPropertyProvider
    {
        private FrtRefHeaderU frtRefHeaderU;
        private bool fIsCF12;
        private ushort nID;
        internal CFExNonCF12 rgbContent;

        public CFExRecord(Range range, StandardConditionalFormattingRule rule, ushort id, BiffWriterWorkbookContext context)
        {
            this.frtRefHeaderU = new FrtRefHeaderU();

            frtRefHeaderU.rt = (ushort) 0x87b;
            frtRefHeaderU.grbitFrt = FrtFlags.fFrtAlert;
            frtRefHeaderU.ref8 = (Ref8) range.Address;
            nID = id;
            CFExTemplateParams parameters;
            if (rule is AboveAverageFormattingRule)
            {
                parameters = new CFExAveragesTemplateParams();
            }

            else if (rule is BeginsWithFormattingRule)
                parameters = new CFExTextTemplateParams(TextTemplateParamsType.TextBeginsWith);
            else if (rule is EndsWithFormattingRule)
                parameters = new CFExTextTemplateParams(TextTemplateParamsType.TextEndsWith);
            else if (rule is ContainsTextFormattingRule)
                parameters = new CFExTextTemplateParams(TextTemplateParamsType.TextContains);
            else if (rule is NotContainsTextFormattingRule)
                parameters = new CFExTextTemplateParams(TextTemplateParamsType.TextDoesNotContain);
            else if (rule is ContainsBlankFormattingRule)
                parameters = new CFExTextTemplateParams(TextTemplateParamsType.TextContains);
            else if (rule is NotContainsBlanksFormattingRule)
                parameters = new CFExTextTemplateParams(TextTemplateParamsType.TextDoesNotContain);
            else if (rule is ContainsErrorsFormattingRule)
                parameters = new CFExTextTemplateParams(TextTemplateParamsType.TextContains);
            else if (rule is NotContainsErrorsFormattingRule)
                parameters = new CFExTextTemplateParams(TextTemplateParamsType.TextDoesNotContain);
            else if (rule is CellIsFormattingRule)
                parameters = new CFExDefaultTemplateParams();
            else if (rule is ExpressionFormattingRule)
                parameters = new CFExDefaultTemplateParams();
            else if (rule is DuplicateValuesFormattingRule)
                parameters = new CFExDefaultTemplateParams();
            else if (rule is UniqueValuesFormattingRule)
                parameters = new CFExDefaultTemplateParams();
            else if (rule is TimePeriodFormattingRule)
                parameters = new CFExDefaultTemplateParams();
            else
            {
                throw new NotImplementedException(rule.ToString());
            }
            StandardConditionalFormattingRule standardConditionalFormattingRule = (StandardConditionalFormattingRule) rule;
            this.rgbContent = new CFExNonCF12(parameters, context, standardConditionalFormattingRule);
            rgbContent.fHasDXF = true;
            rgbContent.fStopIfTrue = rule.StopIfTrue;
            rgbContent.ipriority = (ushort) rule.Priority;
            rgbContent.fActive = true; //\\?
            var differentialStyleRecord = rule.DifferentialStyleRecord;
            if (differentialStyleRecord.Background != null)
            {
                var background = differentialStyleRecord.Background;
                PatternFill fill = (PatternFill) background;
                AddProperty(ExtPropType.BackgroundColor, fill.BackgroundColor);
            }
            if (differentialStyleRecord.Alignment != null)
            {
                throw new NotImplementedException();
            }
            if (differentialStyleRecord.Borders != null)
            {
                throw new NotImplementedException();
            }
            if (differentialStyleRecord.Font != null)
            {
                var font = differentialStyleRecord.Font;
                var color = font.Foreground;
                if (color != null)
                    AddProperty(ExtPropType.ForegroundColor, color);
            }
            if (differentialStyleRecord.Format != null)
            {
                throw new NotImplementedException();
            }
            if (differentialStyleRecord.NumberFormat != null)
            {
                throw new NotImplementedException();
            }
            if (differentialStyleRecord.Protection != null)
            {
                throw new NotImplementedException();
            }
            

            
        }
        public T GetPropertyValue<T>(ExtPropType type) where T : ExtPropValueBase
        {
            foreach (var prop in Properties)
            {
                if (prop.extType == type)
                    return (T)prop.value;

            }
            return null;
        }

        private void AddProperty(ExtPropType type, SpreadsheetColor backgroundColor)
        {
            this.rgbContent.dxf.AddProperty(ExtProp.Create(type, backgroundColor));
        }

        public CFExRecord()
        {
        }

        public IEnumerable<ExtProp> Properties
        {
            get
            {
                return this.rgbContent.dxf.xfext.ExtProps;

            }
        }
        protected override void ReadContent(BiffReaderContext context, int length)
        {
#if DEBUG
            var position = context.Reader.BaseStream.Position;
#endif
            ReadReader(context.Reader);
        }
        void ReadReader(BinaryReader reader)
        {
#if DEBUG
            ReadWriteChecker.CheckClass((t, r) => t.ReadReader(r),
                                   (t, w) => t.WriteWriter(w), reader, this);
#endif
            this.frtRefHeaderU = new FrtRefHeaderU();
            frtRefHeaderU.Read(reader);
            this.fIsCF12 = reader.ReadUInt32() != 0;
            this.nID = reader.ReadUInt16();
            this.rgbContent = new CFExNonCF12();
            rgbContent.Read(reader);
        }
        public CFExTemplateParams TemplateParameters
        {
            get
            {
                return rgbContent.RgbTemplateParms;
            }
        }

        internal override BiffRecordType RecordType
        {
            get { return BiffRecordType.CFEx; }
        }

        internal override void Apply(BiffReaderWorksheetContext context)
        {
            var cfRecord = context.GetCondFmtRecord(nID);
            if (cfRecord == null)
                return;
            cfRecord.CfExRecords.Add(this);
        }

        internal override void WriteContent(BiffWriterWorkbookContext context)
        {
#if DEBUG
            var position = context.Writer.BaseStream.Position;
#endif
            WriteWriter(context.Writer);
            

        }
        void WriteWriter(BinaryWriter writer)
        {
#if DEBUG
            var position = writer.BaseStream.Position;
#endif
            frtRefHeaderU.Write(writer);
            if (fIsCF12)
                writer.Write((uint)1);
            else
            {
                writer.Write((uint)0);
            }
            writer.Write(nID);
            rgbContent.Write(writer);

        }
    }
}